// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#pragma once

#include <stddef.h>

#include "common/pod-class.h"
#include "generic-ops.h"

namespace crypto {

    extern "C" {
#include "hash-ops.h"
    }

#pragma pack(push, 1)
    POD_CLASS hash{
        char data[HASH_SIZE];
    };
    POD_CLASS hash8{
        char data[8];
    };

#pragma pack(pop)

    static_assert(sizeof(hash) == HASH_SIZE, "Invalid structure size");
    static_assert(sizeof(hash8) == 8, "Invalid structure size");

    /*
      Cryptonight hash functions
    */

    inline void cn_fast_hash(const void *data, std::size_t length, hash &hash) {
        cn_fast_hash(data, length, reinterpret_cast<char *>(&hash));
    }

    inline hash cn_fast_hash(const void *data, std::size_t length) {
        hash h;
        cn_fast_hash(data, length, reinterpret_cast<char *>(&h));
        return h;
    }

    inline void cn_slow_hash(const void *data, std::size_t length, hash &hash) {
        cn_slow_hash(data, length, reinterpret_cast<char *>(&hash));
    }

    inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) {
        tree_hash(reinterpret_cast<const char (*)[HASH_SIZE]>(hashes), count, reinterpret_cast<char *>(&root_hash));
    }

    inline void tree_branch(const hash *hashes, std::size_t count, hash *branch) {
        tree_branch(reinterpret_cast<const char (*)[HASH_SIZE]>(hashes), count,
                    reinterpret_cast<char (*)[HASH_SIZE]>(branch));
    }

    inline void
    tree_hash_from_branch(const hash *branch, std::size_t depth, const hash &leaf, const void *path, hash &root_hash) {
        tree_hash_from_branch(reinterpret_cast<const char (*)[HASH_SIZE]>(branch), depth,
                              reinterpret_cast<const char *>(&leaf), path, reinterpret_cast<char *>(&root_hash));
    }

}

CRYPTO_MAKE_HASHABLE(hash)
CRYPTO_MAKE_COMPARABLE(hash8)
